Import Packages

library(ggplot2)
library(plotly)
library(data.table)


Import Data and look at first couple records

setwd("F:/kaggle/Mercedes-Benz")
sample_submission <- fread("data/sample_submission.csv")
train <- fread("data/train.csv")
test <- fread("data/test.csv")
train[1:2,]
# 1 - ID
# 2 - Response Varuable (Time in Seconds on Test Stand)
# 3-10  String Option Codes
# 11-385 0/1 values based on option codes
# X7 and X9 are missinf for some reason.


Calculate Mean and SD for Response Variable (Y). This is the time (sec) for a vehicle on the MB test station.

mean(train[,y])
[1] 100.6693
sd(train[,y])
[1] 12.67938


Create plots for the Response Variable. Sorted by ID.

plot_ly(y=train$y, type="scatter")


Create plots for the Response Variable. Sorted by the Response Variable.

plot_ly(y=train[order(y),]$y, type="scatter")


Create histogram for the Response Variable.

 plot_ly(x=train$y, type="histogram")


Create histogram for the LOG(Response Variable).

 plot_ly(x=log(train$y), type="histogram")


Frequency tables for the first 10 variables (All with String Codes)

train[,.N,by=X0][order(-N)]
train[,.N,by=X1][order(-N)]
train[,.N,by=X2][order(-N)]
train[,.N,by=X3][order(-N)]
train[,.N,by=X4][order(-N)]
train[,.N,by=X5][order(-N)]
train[,.N,by=X6][order(-N)]
train[,.N,by=X8][order(-N)] #where is 7
train[,.N,by=X10][order(-N)] #where is 9


Frequency plots for the first 10 variables (All with String Codes)

# column_names_for_option_plots_string_codes <- colnames(train)[3:5] #3:12
# for(i in column_names_for_option_plots_string_codes){
#   x_values <- as.data.frame(train[,.N,by=i][order(-N)])[,i]
#   y_values <- as.data.frame(train[,.N,by=i][order(-N)])[,'N']
#   plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar")
##Couldn't get loop plotting to work => https://github.com/ropensci/plotly/issues/273
#Plotting manually
column_names_for_option_plots_string_codes <- colnames(train)[3:10] #3:10
i<-1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)

i<-i+1
current_colname <- column_names_for_option_plots_string_codes[i]
x_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,current_colname]
y_values <- as.data.frame(train[,.N,by=current_colname][order(-N)])[,'N']
plot_ly(x=as.list(x_values),y=as.list(y_values), type="bar") %>% layout(title=current_colname)


Frequency table for the remaining variables (All with 0/1 Coding)

column_names_for_summary <- colnames(train)[11:length(colnames(train))]
Variable <- c()
N_0 <- c()
N_1 <- c()
for(i in column_names_for_summary){
  j=1
  Variable <- c(Variable,i)
  N_0 <- c(N_0,train[,.N,by=i][1]$N)
  N_1 <- c(N_1,train[,.N,by=i][2]$N)
  j <- j+1
}
N_0[is.na(N_0)==TRUE] <- 0
N_1[is.na(N_1)==TRUE] <- 0
summary_results <- as.data.frame(cbind(Variable,N_0,N_1), stringsAsFactors = FALSE)
summary_results


After Looking at Kaggle, checked for Duplicate fileds - Added Data to Frequency table for the remaining variables (All with 0/1 Coding).

train_2 <- train[, !duplicated(t(train))]
duplicate_column <- c()
for(i in duplicated(t(train))){
  duplicate_column <- c(duplicate_column,i)
}
duplicate_column <- duplicate_column[11:length(duplicate_column)]
summary_results$duplicate_column <- duplicate_column
summary_results_decreasing <- summary_results[order(-N_1),]
summary_results
summary_results_decreasing


List of Duplicated Columns

summary_results_decreasing[(summary_results_decreasing$duplicate_column==TRUE),]


Correlation Matrix of Features after removing duplicates

library(ggcorrplot)

train_2 <- train[, !duplicated(t(train))] #remove duplicated fields ... from raddar@Kaggle => https://www.kaggle.com/c/mercedes-benz-greener-manufacturing/discussion/34006
ggcorrplot(cor(train_2), p.mat = cor_pmat(train_2), hc.order=TRUE, type='lower')
LS0tDQp0aXRsZTogIk1lcmNlZGVzLUJlbnogRURBIE5vdGVib29rIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQphdXRob3I6IEplZmYgSGVkYmVyZw0KZGF0ZTogNS1KdW5lLTIwMTcgICAgDQotLS0NCjxicj4NCg0KIyMjIyBJbXBvcnQgUGFja2FnZXMNCmBgYHtyLHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoZGF0YS50YWJsZSkNCmBgYA0KDQo8YnI+DQoNCiMjIyMgIEltcG9ydCBEYXRhIGFuZCBsb29rIGF0IGZpcnN0IGNvdXBsZSByZWNvcmRzDQpgYGB7cixyb3dzLnByaW50PTUsIGNvbHMucHJpbnQ9NTAwfQ0Kc2V0d2QoIkY6L2thZ2dsZS9NZXJjZWRlcy1CZW56IikNCg0Kc2FtcGxlX3N1Ym1pc3Npb24gPC0gZnJlYWQoImRhdGEvc2FtcGxlX3N1Ym1pc3Npb24uY3N2IikNCnRyYWluIDwtIGZyZWFkKCJkYXRhL3RyYWluLmNzdiIpDQp0ZXN0IDwtIGZyZWFkKCJkYXRhL3Rlc3QuY3N2IikNCg0KdHJhaW5bMToyLF0NCg0KIyAxIC0gSUQNCiMgMiAtIFJlc3BvbnNlIFZhcnVhYmxlIChUaW1lIGluIFNlY29uZHMgb24gVGVzdCBTdGFuZCkNCiMgMy0xMCAgU3RyaW5nIE9wdGlvbiBDb2Rlcw0KIyAxMS0zODUgMC8xIHZhbHVlcyBiYXNlZCBvbiBvcHRpb24gY29kZXMNCg0KIyBYNyBhbmQgWDkgYXJlIG1pc3NpbmYgZm9yIHNvbWUgcmVhc29uLg0KYGBgDQo8YnI+DQoNCiMjIyMgIENhbGN1bGF0ZSBNZWFuIGFuZCBTRCBmb3IgUmVzcG9uc2UgVmFyaWFibGUgKFkpLiAgVGhpcyBpcyB0aGUgdGltZSAoc2VjKSBmb3IgYSB2ZWhpY2xlIG9uIHRoZSBNQiB0ZXN0IHN0YXRpb24uDQpgYGB7cn0NCm1lYW4odHJhaW5bLHldKQ0Kc2QodHJhaW5bLHldKQ0KYGBgDQo8YnI+DQoNCiMjIyMgIENyZWF0ZSBwbG90cyBmb3IgdGhlIFJlc3BvbnNlIFZhcmlhYmxlLiAgU29ydGVkIGJ5IElELg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpwbG90X2x5KHk9dHJhaW4keSwgdHlwZT0ic2NhdHRlciIpDQpgYGANCjxicj4NCg0KIyMjIyAgQ3JlYXRlIHBsb3RzIGZvciB0aGUgUmVzcG9uc2UgVmFyaWFibGUuICBTb3J0ZWQgYnkgdGhlIFJlc3BvbnNlIFZhcmlhYmxlLg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQpwbG90X2x5KHk9dHJhaW5bb3JkZXIoeSksXSR5LCB0eXBlPSJzY2F0dGVyIikNCmBgYA0KPGJyPg0KDQojIyMjICBDcmVhdGUgaGlzdG9ncmFtIGZvciB0aGUgUmVzcG9uc2UgVmFyaWFibGUuDQpgYGB7cn0NCiBwbG90X2x5KHg9dHJhaW4keSwgdHlwZT0iaGlzdG9ncmFtIikNCmBgYA0KPGJyPg0KDQojIyMjICBDcmVhdGUgaGlzdG9ncmFtIGZvciB0aGUgTE9HKFJlc3BvbnNlIFZhcmlhYmxlKS4NCmBgYHtyfQ0KIHBsb3RfbHkoeD1sb2codHJhaW4keSksIHR5cGU9Imhpc3RvZ3JhbSIpDQpgYGANCjxicj4NCg0KIyMjIyAgRnJlcXVlbmN5IHRhYmxlcyBmb3IgdGhlIGZpcnN0IDEwIHZhcmlhYmxlcyAoQWxsIHdpdGggU3RyaW5nIENvZGVzKQ0KYGBge3IsIHJvd3MucHJpbnQ9NTAwLCBjb2xzLnByaW50PTV9DQp0cmFpblssLk4sYnk9WDBdW29yZGVyKC1OKV0NCnRyYWluWywuTixieT1YMV1bb3JkZXIoLU4pXQ0KdHJhaW5bLC5OLGJ5PVgyXVtvcmRlcigtTildDQp0cmFpblssLk4sYnk9WDNdW29yZGVyKC1OKV0NCnRyYWluWywuTixieT1YNF1bb3JkZXIoLU4pXQ0KdHJhaW5bLC5OLGJ5PVg1XVtvcmRlcigtTildDQp0cmFpblssLk4sYnk9WDZdW29yZGVyKC1OKV0NCnRyYWluWywuTixieT1YOF1bb3JkZXIoLU4pXSAjd2hlcmUgaXMgNw0KdHJhaW5bLC5OLGJ5PVgxMF1bb3JkZXIoLU4pXSAjd2hlcmUgaXMgOQ0KDQpgYGANCjxicj4NCg0KIyMjIyAgRnJlcXVlbmN5IHBsb3RzIGZvciB0aGUgZmlyc3QgMTAgdmFyaWFibGVzIChBbGwgd2l0aCBTdHJpbmcgQ29kZXMpDQpgYGB7cn0NCiMgY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzIDwtIGNvbG5hbWVzKHRyYWluKVszOjVdICMzOjEyDQojIGZvcihpIGluIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlcyl7DQojICAgeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9aV1bb3JkZXIoLU4pXSlbLGldDQojICAgeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9aV1bb3JkZXIoLU4pXSlbLCdOJ10NCiMgICBwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikNCiMjQ291bGRuJ3QgZ2V0IGxvb3AgcGxvdHRpbmcgdG8gd29yayA9PiBodHRwczovL2dpdGh1Yi5jb20vcm9wZW5zY2kvcGxvdGx5L2lzc3Vlcy8yNzMNCg0KI1Bsb3R0aW5nIG1hbnVhbGx5DQpjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXMgPC0gY29sbmFtZXModHJhaW4pWzM6MTBdICMzOjEwDQppPC0xDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQppPC1pKzENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCmk8LWkrMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KaTwtaSsxDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQppPC1pKzENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCmk8LWkrMQ0KY3VycmVudF9jb2xuYW1lIDwtIGNvbHVtbl9uYW1lc19mb3Jfb3B0aW9uX3Bsb3RzX3N0cmluZ19jb2Rlc1tpXQ0KeF92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssY3VycmVudF9jb2xuYW1lXQ0KeV92YWx1ZXMgPC0gYXMuZGF0YS5mcmFtZSh0cmFpblssLk4sYnk9Y3VycmVudF9jb2xuYW1lXVtvcmRlcigtTildKVssJ04nXQ0KcGxvdF9seSh4PWFzLmxpc3QoeF92YWx1ZXMpLHk9YXMubGlzdCh5X3ZhbHVlcyksIHR5cGU9ImJhciIpICU+JSBsYXlvdXQodGl0bGU9Y3VycmVudF9jb2xuYW1lKQ0KaTwtaSsxDQpjdXJyZW50X2NvbG5hbWUgPC0gY29sdW1uX25hbWVzX2Zvcl9vcHRpb25fcGxvdHNfc3RyaW5nX2NvZGVzW2ldDQp4X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWyxjdXJyZW50X2NvbG5hbWVdDQp5X3ZhbHVlcyA8LSBhcy5kYXRhLmZyYW1lKHRyYWluWywuTixieT1jdXJyZW50X2NvbG5hbWVdW29yZGVyKC1OKV0pWywnTiddDQpwbG90X2x5KHg9YXMubGlzdCh4X3ZhbHVlcykseT1hcy5saXN0KHlfdmFsdWVzKSwgdHlwZT0iYmFyIikgJT4lIGxheW91dCh0aXRsZT1jdXJyZW50X2NvbG5hbWUpDQppPC1pKzENCmN1cnJlbnRfY29sbmFtZSA8LSBjb2x1bW5fbmFtZXNfZm9yX29wdGlvbl9wbG90c19zdHJpbmdfY29kZXNbaV0NCnhfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLGN1cnJlbnRfY29sbmFtZV0NCnlfdmFsdWVzIDwtIGFzLmRhdGEuZnJhbWUodHJhaW5bLC5OLGJ5PWN1cnJlbnRfY29sbmFtZV1bb3JkZXIoLU4pXSlbLCdOJ10NCnBsb3RfbHkoeD1hcy5saXN0KHhfdmFsdWVzKSx5PWFzLmxpc3QoeV92YWx1ZXMpLCB0eXBlPSJiYXIiKSAlPiUgbGF5b3V0KHRpdGxlPWN1cnJlbnRfY29sbmFtZSkNCg0KYGBgDQo8YnI+DQoNCiMjIyMgIEZyZXF1ZW5jeSB0YWJsZSBmb3IgdGhlIHJlbWFpbmluZyB2YXJpYWJsZXMgKEFsbCB3aXRoIDAvMSBDb2RpbmcpDQpgYGB7ciwgcm93cy5wcmludD01MDAsIGNvbHMucHJpbnQ9NX0NCmNvbHVtbl9uYW1lc19mb3Jfc3VtbWFyeSA8LSBjb2xuYW1lcyh0cmFpbilbMTE6bGVuZ3RoKGNvbG5hbWVzKHRyYWluKSldDQpWYXJpYWJsZSA8LSBjKCkNCk5fMCA8LSBjKCkNCk5fMSA8LSBjKCkNCg0KZm9yKGkgaW4gY29sdW1uX25hbWVzX2Zvcl9zdW1tYXJ5KXsNCiAgaj0xDQogIFZhcmlhYmxlIDwtIGMoVmFyaWFibGUsaSkNCiAgTl8wIDwtIGMoTl8wLHRyYWluWywuTixieT1pXVsxXSROKQ0KICBOXzEgPC0gYyhOXzEsdHJhaW5bLC5OLGJ5PWldWzJdJE4pDQogIGogPC0gaisxDQp9DQoNCk5fMFtpcy5uYShOXzApPT1UUlVFXSA8LSAwDQpOXzFbaXMubmEoTl8xKT09VFJVRV0gPC0gMA0KDQpzdW1tYXJ5X3Jlc3VsdHMgPC0gYXMuZGF0YS5mcmFtZShjYmluZChWYXJpYWJsZSxOXzAsTl8xKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0Kc3VtbWFyeV9yZXN1bHRzDQpgYGANCjxicj4NCg0KIyMjIyAgQWZ0ZXIgTG9va2luZyBhdCBLYWdnbGUsIGNoZWNrZWQgZm9yIER1cGxpY2F0ZSBmaWxlZHMgLSBBZGRlZCBEYXRhIHRvIEZyZXF1ZW5jeSB0YWJsZSBmb3IgdGhlIHJlbWFpbmluZyB2YXJpYWJsZXMgKEFsbCB3aXRoIDAvMSBDb2RpbmcpLg0KYGBge3IsIHJvd3MucHJpbnQ9NTAwLCBjb2xzLnByaW50PTV9DQp0cmFpbl8yIDwtIHRyYWluWywgIWR1cGxpY2F0ZWQodCh0cmFpbikpXSAjcmVtb3ZlIGR1cGxpY2F0ZWQgZmllbGRzIC4uLiBmcm9tIHJhZGRhckBLYWdnbGUgPT4gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9jL21lcmNlZGVzLWJlbnotZ3JlZW5lci1tYW51ZmFjdHVyaW5nL2Rpc2N1c3Npb24vMzQwMDYNCmR1cGxpY2F0ZV9jb2x1bW4gPC0gYygpDQpmb3IoaSBpbiBkdXBsaWNhdGVkKHQodHJhaW4pKSl7DQogIGR1cGxpY2F0ZV9jb2x1bW4gPC0gYyhkdXBsaWNhdGVfY29sdW1uLGkpDQp9DQoNCmR1cGxpY2F0ZV9jb2x1bW4gPC0gZHVwbGljYXRlX2NvbHVtblsxMTpsZW5ndGgoZHVwbGljYXRlX2NvbHVtbildDQoNCnN1bW1hcnlfcmVzdWx0cyRkdXBsaWNhdGVfY29sdW1uIDwtIGR1cGxpY2F0ZV9jb2x1bW4NCg0Kc3VtbWFyeV9yZXN1bHRzX2RlY3JlYXNpbmcgPC0gc3VtbWFyeV9yZXN1bHRzW29yZGVyKC1OXzEpLF0NCg0Kc3VtbWFyeV9yZXN1bHRzDQpzdW1tYXJ5X3Jlc3VsdHNfZGVjcmVhc2luZw0KYGBgDQo8YnI+DQoNCiMjIyMgIExpc3Qgb2YgRHVwbGljYXRlZCBDb2x1bW5zDQpgYGB7ciwgcm93cy5wcmludD0xMDAsIGNvbHMucHJpbnQ9NX0NCnN1bW1hcnlfcmVzdWx0c19kZWNyZWFzaW5nWyhzdW1tYXJ5X3Jlc3VsdHNfZGVjcmVhc2luZyRkdXBsaWNhdGVfY29sdW1uPT1UUlVFKSxdDQpgYGANCjxicj4NCg0KIyMjIyAgQ29ycmVsYXRpb24gTWF0cml4IG9mIEZlYXR1cmVzIGFmdGVyIHJlbW92aW5nIGR1cGxpY2F0ZXMNCmBgYHtyfQ0KbGlicmFyeShnZ2NvcnJwbG90KQ0KDQp0cmFpbl8yIDwtIHRyYWluWywgIWR1cGxpY2F0ZWQodCh0cmFpbikpXSAjcmVtb3ZlIGR1cGxpY2F0ZWQgZmllbGRzIC4uLiBmcm9tIHJhZGRhckBLYWdnbGUgPT4gaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9jL21lcmNlZGVzLWJlbnotZ3JlZW5lci1tYW51ZmFjdHVyaW5nL2Rpc2N1c3Npb24vMzQwMDYNCmdnY29ycnBsb3QoY29yKHRyYWluXzIpLCBwLm1hdCA9IGNvcl9wbWF0KHRyYWluXzIpLCBoYy5vcmRlcj1UUlVFLCB0eXBlPSdsb3dlcicpDQpgYGANCg0KDQoNCg0KDQoNCg==